﻿using System;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
using Autofac;
using Newtonsoft.Json.Linq;
using Pay.Core;
using Pay.Core.WeiXin;
using Pay.DTO;
using Pay.DTO.hfnative;
using Pay.DTO.jwuct;
using Pay.IService;
using Pay.Service;
using Pay.TO;

namespace Pay.Api.Controllers {
	/// <summary>
	/// 扫码支付
	/// </summary>
	public partial class OpenController : BaseController {
		/// <summary>
		/// 扫码支付
		/// </summary>
		/// <returns>The pay.</returns>
		/// <param name="model">Model.</param>
		protected async Task<native_result> NativePay(native_model model) {
			if (model.type == 0) model.type = 1;
			if (string.IsNullOrEmpty(model.order_no))
				return ApiResultToJson.Json<native_result>("订单号不能为空");
			else {
				if (model.order_no.Length < 13)
					return ApiResultToJson.Json<native_result>("订单号最小14位");
				if (model.order_no.Length > 31)
					return ApiResultToJson.Json<native_result>("订单号最大长度30位");
			}
			if (string.IsNullOrEmpty(model.tran_amount))
				return ApiResultToJson.Json<native_result>("交易金额不能为空");
			if (string.IsNullOrEmpty(model.settle_type))
				return ApiResultToJson.Json<native_result>("结算类型不能为空");
			if (string.IsNullOrEmpty(model.pay_code))
				return ApiResultToJson.Json<native_result>("支付方式不能为空");
			if (string.IsNullOrEmpty(model.notify))
				return ApiResultToJson.Json<native_result>("支付成功后服务器回调该地址不能为空");
			if (model.pay_channel == PayChannel.None)
				return ApiResultToJson.Json<native_result>("通道不能为空");

			model.pay_type = PayType.Native;
			if (model.pay_code == "WXPAY_APP")
				model.pay_type = PayType.SDK;
			else if (model.pay_code == "WXPAY_JS" || model.pay_code == "ALIPAY_JS")
				model.pay_type = PayType.JSPAY;

			//把商户请求转为通道请求消息
			var _iPayService = _iocContext.ResolveKeyed<IPayService>(model.pay_channel);
			var data = await _iPayService.NativePay(model);
			return data;
		}

		/// <summary>
		/// 扫码APP支付升级
		/// </summary>
		/// <returns>The pay up.</returns>
		/// <param name="model">Object.</param>
		protected async Task<native_result> NativePayUp(native_model model) {
			model.type = 2;
			return await NativePay(model);
		}
		/// <summary>
		/// hf扫码通道回调通知
		/// </summary>
		/// <returns>The notify.</returns>
		/// <param name="model">Model.</param>
		[Route("hf_native_notify/{id}"), HttpPost, HttpGet, AllowAnonymous]
		public async Task<string> HfNativeNotify(string id, string settle_type, [FromBody]JObject model) {
			var log = IocHelper.Get<ILogHelper>("info");
			log.Info("hf异步通知了:" + id);
			log.Info(model.ToString());
			var _hfSign = new HfSign();
			var data = model.ToObject<pay_native_notify>();
			//if (_hfSign.VerifySign(model, data.sign, settle_type)) {
			log.Info("hf异步通知成功:" + data.channelOrderNo);
			var result = 0;
			var obj = _iPayHtmlService.Get(id);
			charge_dto charge = null;
			if (obj != null) {
				charge = obj.charge.ToObject<charge_dto>();
			} else {
				log.Info("hf－nosql获取失败:" + data.outTradeNo);
				return "失败";
			}
			var order = _iChargeService.Get(charge.merchant_no, data.outTradeNo);
			//因为同进同出HTML的生成是用mongodb，所以要查数据库订单生成了没有，没有生成则调用返回参数处理
			if (order == null) {
				if (data.returnCode == "0") {
					if (data.resultCode == "0") {
						if (data.status == "02") {
							var dt = data.transTime.ToDateTime();
							result = _iChargeService.PaySuceess(obj, data.channelOrderNo, dt);
							if (result > 0) {
								var _iPayService = _iocContext.ResolveKeyed<IPayService>(charge.pay_info.pay_channel);
								//T0直接代付
								if (charge.pay_info.settle_type == "T0") {
									var itn = await _iPayService.Transfer(new apply_transfer {
										merchant_no = charge.merchant_no, bind_no = charge.bind_no, notify = "", order_no = charge.order_no,
										pay_channel = charge.pay_info.pay_channel, pay_code = charge.pay_info.pay_code,
										settle_type = charge.pay_info.settle_type, tran_amount = ((int)((charge.amount - charge.settle_fee) * 100)).ToString()
									});
								}
								//通知APP
								var notifyResult = await _iPayService.Notify(charge.merchant_no, charge.order_no);
								if (notifyResult != "OK") {
									//创建通知消息对象
									_iPayNotifyService.Save(new pay_notify_dto {
										merchant_no = charge.merchant_no, order_no = charge.order_no, pay_channel = charge.pay_info.pay_channel, type = 1,
										status = 2, create_time = DateTime.Now
									});
								}
								_iPayHtmlService.Remove(id);
							}
						}
					} else {
						result = _iChargeService.PayFail(obj, data.channelOrderNo, data.errCodeDes);
					}
				} else {
					result = _iChargeService.PayFail(obj, data.channelOrderNo, data.returnMsg);
				}
			} else
				return "SUCCESS";
			//回执成功，通道不会再通知
			if (result > 0) {
				return "SUCCESS";
			}
			log.Info("hf-保存数据库订单失败:" + data.outTradeNo);
			return "fail";
			//}
			//log.Info("hf-签名不正确:" + data.outTradeNo);
			//return "签名不正确";
		}

		/// <summary>
		/// jwuct扫码通道回调通知
		/// </summary>
		/// <returns>The notify.</returns>
		/// <param name="model">Model.</param>
		[Route("jwuct_native_notify"), HttpPost, HttpGet, AllowAnonymous]
		public object JwuctNativeNotify([FromBody]JObject model) {
			lock (jwuctLock) {
				var _jwuctSign = new JwuctSign();
				if (_jwuctSign.VerifySign(model)) {
					var dto = model.ToObject<jwuct_notity>();
					var result = 0;
					var order = _iChargeService.GetByTran(dto.orderNo);
					if (dto.resultCode == "00" && dto.resCode == "00" && decimal.Parse(dto.orderAmt) / 100 == order.pay_amount) {
						var dt = dto.createTime.ToDateTime();
						if (order.status != ChargeStatus.Finish)
							result = _iChargeService.FailOrUnConfirmToSuceess(order.merchant_no, dto.outTradeNo, dt, dto.orderNo);
					} else {
						//if (order.status == ChargeStatus.WaitPay)
						//	result = _iChargeService.PayFail(obj, dto.orderNo, dto.resDesc);
					}
					//回执成功，通道不会再通知
					if (result > 0) {
						return new { resCode = "00", resDesc = "成功了" };
					}
				}
				return new { resCode = "01", resDesc = "签名不正确" };
			}
		}

		/// <summary>
		/// SFB扫码、APP支付升级回调
		/// </summary>
		/// <returns>The native notify.</returns>
		/// <param name="id">Identifier.</param>
		[Route("sfb_native_notify/{id}"), HttpPost, HttpGet, AllowAnonymous]
		public async Task<string> SfbNativeNotify(string id) {
			var log = IocHelper.Get<ILogHelper>("info");
			log.Info("sfb异步通知了:" + id);
			var payment = new payment_query { key = "e590999272769b5d0e78726848f99ad7" };
			ResponseHandler resHandler = new ResponseHandler(null);
			string return_code = resHandler.GetParameter("return_code");
			string return_msg = resHandler.GetParameter("return_msg");
			resHandler.SetKey(payment.key);
			if (resHandler.IsTenpaySign()) {
				var pay_no = resHandler.GetParameter("out_trade_no");
				log.Info("sfb异步通知成功:" + pay_no);
				var result = 0;
				var obj = _iPayHtmlService.Get(id);
				charge_dto charge = null;
				if (obj != null) {
					charge = obj.charge.ToObject<charge_dto>();
				} else {
					log.Info("sfb－nosql获取失败:" + pay_no);
					return "<xml><return_code><![CDATA[fail]]></return_code></xml>";
				}
				var order = _iChargeService.Get(charge.merchant_no, pay_no);
				if (order == null) {
					string transaction_no = resHandler.GetParameter("transaction_id");
					if (return_code == "SUCCESS") {
						string time_end = resHandler.GetParameter("time_end");
						DateTime pay_time = time_end.ToDateTime();
						result = _iChargeService.PaySuceess(obj, transaction_no, pay_time);
						if (result > 0) {
							var _iPayService = _iocContext.ResolveKeyed<IPayService>(charge.pay_info.pay_channel);
							var notifyResult = await _iPayService.Notify(charge.merchant_no, charge.order_no);
							if (notifyResult != "OK") {
								//创建通知消息对象
								_iPayNotifyService.Save(new pay_notify_dto {
									merchant_no = charge.merchant_no, order_no = charge.order_no, pay_channel = charge.pay_info.pay_channel, type = 1,
									status = 2, create_time = DateTime.Now
								});
							}
							_iPayHtmlService.Remove(id);
						}
					} else {
						result = _iChargeService.PayFail(obj, transaction_no, return_msg);
					}
				} else {
					//存在成功
					return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
				}
				//回执成功，通道不会再通知
				if (result > 0) {
					return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
				}
				log.Info("sfb-保存数据库订单失败:" + pay_no);
				return "<xml><return_code><![CDATA[fail]]></return_code></xml>";
			}
			log.Info("sfb-签名不正确:" + id);
			return "<xml><return_code><![CDATA[签名不正确]]></return_code></xml>";
		}
	}
}
